#!/usr/bin/python


import random
from typing import Any

from paho.mqtt import client as mqtt_client

import time

import json
from log_class import Logger

# broker = '127.0.0.1'
# port = 1883
# # generate client ID with pub prefix randomly
# client_id = f'python-mqtt-{random.randint(0, 100)}'

log = Logger('log_files/log_record.log', level='debug')


class WuxiMqttClass:

    def __init__(self, broker, port, obj) -> None:
        self.broker = broker
        self.port = port
        self.obj = obj
        self.client_id = self.make_client()
        self.client = self.connect_mqtt()
        # self.client.loop_start()
        # self.client.loop_forever()

    def make_client(self):
        client_id = f'python-mqtt-{random.randint(0, 1000)}'
        return client_id

    def on_connect(self, client, userdata, flags, rc):
        if rc == 0:
            # print("Connected to MQTT Broker!")
            log.logger.info("Connected to MQTT Broker!")
        else:
            # print("Failed to connect, return code %d\n", rc)
            log.logger.info("Failed to connect, return code %d\n", rc)

    def connect_mqtt(self) -> mqtt_client:
        client = mqtt_client.Client(self.client_id)
        client.on_connect = self.on_connect
        client.connect(self.broker, self.port)
        return client

    def on_message(self, client, userdata, message):
        print('message.payload', message.payload)
        try:
            payload = json.loads(message.payload)
        except:
            topic = message.topic + '/response'
            res = json.dumps(
                {
                    "status": 1,
                    "message": "Request parameter format error"
                }
            )
            self.publish_topic(topic, res)
            return None
        if message.topic == 'wuxi/beamLightControl':
            self.beam_control(payload)
        elif message.topic == 'wuxi/brakeLightControl':
            self.brake_control(payload)

        elif message.topic == 'wuxi/directionLeftLightControl':
            self.direction_left_control(payload)

        elif message.topic == 'wuxi/directionRightLightControl':
            self.direction_right_control(payload)

        elif message.topic == 'wuxi/wiperControl':
            self.wiper_control(payload)

        elif message.topic == 'wuxi/ambientControl':
            self.ambient_control(payload)
        elif message.topic == 'wuxi/customControl':
            self.custom_control(payload)
        else:
            # print(f"Received `{message.payload.decode()}` from `{message.topic}` topic")
            log.logger.info(f"Received `{message.payload.decode()}` from `{message.topic}` topic")

    def subscribe_topic_received(self, *args):
        for arg in args:
            # print('sub')
            log.logger.info('sub')
            self.client.subscribe(arg, qos=0)
            # print('ok')
            log.logger.info('ok')
            self.client.on_message = self.on_message

    def publish_topic(self, topic: str, msg: str):
        self.client.publish(topic, msg)

    def beam_control(self, payload: dict):
        # beam has three states
        # status_str = payload['status']
        beam_topic = 'wuxi/beamLightControl/response'
        status_str = payload.get('status', 'no_arg')
        if status_str == 'no_arg':
            res = json.dumps(
                {
                    "status": 0,
                    "message": "not get pected argument"
                }
            )
            self.publish_topic(beam_topic, res)
            return
        status = int(status_str)
        if status == 0:
            # turn off beamlight
            self.obj.setHighBeam(0)
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "beam is turn off"
                }
            )
            self.publish_topic(beam_topic, res)
        elif status == 1:
            # beam is on and the status is steady
            self.obj.setHighBeam(1)
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "hight beam light turn on success"
                }
            )
            self.publish_topic(beam_topic, res)

        else:
            # publish topic
            res = json.dumps(
                {
                    "status": 1,
                    "message": "unknow parameter value"
                }
            )
            self.publish_topic(beam_topic, res)

    def brake_control(self, payload: dict):
        brake_topic = 'wuxi/brakeLightControl/response'

        status_str = payload.get('status', 'no_arg')
        if status_str == 'no_arg':
            res = json.dumps(
                {
                    "status": 0,
                    "message": "not get pected argument"
                }
            )
            self.publish_topic(brake_topic, res)
            return
        status = int(status_str)
        if status == 0:
            # turn off brake light
            self.obj.setBrakeLight(0)
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "brake light is turn off"
                }
            )
            self.publish_topic(brake_topic, res)
        elif status == 1:
            # steady brake light
            self.obj.setBrakeLight(1)
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "brake light is turn on success"
                }
            )
            self.publish_topic(brake_topic, res)
        else:
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "unknow parameter value"
                }
            )
            self.publish_topic(brake_topic, res)

    def direction_left_control(self, payload: dict):
        direction_topic = 'wuxi/directionLeftLightControl/response'
        status_str = payload.get('status', 'no_arg')
        if status_str == 'no_arg':
            res = json.dumps(
                {
                    "status": 0,
                    "message": "not get pected argument"
                }
            )
            self.publish_topic(direction_topic, res)
            return
        status = int(status_str)
        if status == 0:
            # turn off direction light
            self.obj.setLeftTurnLight(0)
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "direction light turn off success"
                }
            )
            self.publish_topic(direction_topic, res)
        elif status == 1:
            # steady brake light
            self.obj.setLeftTurnLight(1)
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "direction light turn on success"
                }
            )
            self.publish_topic(direction_topic, res)
        else:
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "unknow parameter value"
                }
            )
            self.publish_topic(direction_topic, res)

    def direction_right_control(self, payload: dict):
        direction_topic = 'wuxi/directionRightLightControl/response'
        status_str = payload.get('status', 'no_arg')
        if status_str == 'no_arg':
            res = json.dumps(
                {
                    "status": 0,
                    "message": "not get pected argument"
                }
            )
            self.publish_topic(direction_topic, res)
            return
        status = int(status_str)
        if status == 0:
            # turn off direction light
            self.obj.setRightTurnLight(0)
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "direction light turn off success"
                }
            )
            self.publish_topic(direction_topic, res)
        elif status == 1:
            # steady brake light
            self.obj.setRightTurnLight(1)
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "direction light turn on success"
                }
            )
            self.publish_topic(direction_topic, res)
        else:
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "unknow parameter value"
                }
            )
            self.publish_topic(direction_topic, res)

    def wiper_control(self, payload: dict):
        wiper_topic = 'wuxi/wiperControl/response'
        status_str = payload.get('status', 'no_arg')
        if status_str == 'no_arg':
            res = json.dumps(
                {
                    "status": 0,
                    "message": "not get pected argument"
                }
            )
            self.publish_topic(wiper_topic, res)
            return
        status = int(status_str)
        if status == 0:
            # turn off wiper
            self.obj.setWiper(0)
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "wiper is off"
                }
            )
            self.publish_topic(wiper_topic, res)
        elif status == 1:
            # slow wiper
            self.obj.setWiper(1)
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "wiper run slowly speed success"
                }
            )
            self.publish_topic(wiper_topic, res)
        elif status == 2:
            # medium wiper
            self.obj.setWiper(2)
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "wiper run medium speed success"
                }
            )
            self.publish_topic(wiper_topic, res)

        elif status == 3:
            # fast wiper
            self.obj.setWiper(3)
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "wiper run fast speed success"
                }
            )
            self.publish_topic(wiper_topic, res)

        else:
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "unknow parameter value"
                }
            )
            self.publish_topic(wiper_topic, res)

    def ambient_control(self, payload: dict):
        ambient_topic = 'wuxi/ambientControl/response'
        status_str = payload.get('status', 'no_arg')
        if status_str == 'no_arg':
            res = json.dumps(
                {
                    "status": 0,
                    "message": "not get pected argument"
                }
            )
            self.publish_topic(ambient_topic, res)
            return
        status = int(status_str)
        if status == 0:
            # turn off ambient

            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "ambient is off"
                }
            )
            self.publish_topic(ambient_topic, res)
        elif status == 1:
            # # ambient red steady
            self.obj.setLightColor({"R": 60, "G": 0, "B": 0})
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "ambient is red light steady"
                }
            )
            self.publish_topic(ambient_topic, res)
        elif status == 2:
            # orange steady
            self.obj.setLightColor({"R": 60, "G": 23, "B": 0})
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "ambient is orange steady"
                }
            )
            self.publish_topic(ambient_topic, res)

        elif status == 3:
            # yellow steady
            self.obj.setLightColor({"R": 60, "G": 60, "B": 0})
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "ambient is yellow steady"
                }
            )
            self.publish_topic(ambient_topic, res)

        elif status == 4:
            # green steady
            self.obj.setLightColor({"R": 0, "G": 60, "B": 0})
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "ambient is green steady"
                }
            )
            self.publish_topic(ambient_topic, res)

        elif status == 5:
            # cyan steady
            self.obj.setLightColor({"R": 0, "G": 60, "B": 60})
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "ambient is cyan steady"
                }
            )
            self.publish_topic(ambient_topic, res)

        elif status == 6:
            # blue steady
            self.obj.setLightColor({"R": 0, "G": 0, "B": 60})
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "ambient is blue steady"
                }
            )
            self.publish_topic(ambient_topic, res)

        elif status == 7:
            # purple steady
            self.obj.setLightColor({ "R": 160,"G": 32,"B": 240 })
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "ambient is purple steady"
                }
            )
            self.publish_topic(ambient_topic, res)

        elif status == 8:
            # purple flashing
            self.obj.setLightColor({"R": 40, "G": 8, "B": 60})
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "ambient is white steady"
                }
            )
            self.publish_topic(ambient_topic, res)

        else:
            # publish topic
            res = json.dumps(
                {
                    "status": 0,
                    "message": "unknow value"
                }
            )
            self.publish_topic(ambient_topic, res)

    def custom_control(self, payload: dict):
        custom_control_topic = 'wuxi/customerControl/response'
        status_str = payload.get('status', 'no_arg')
        if status_str == 'no_arg':
            res = json.dumps(
                {
                    "status": 0,
                    "message": "not get pected argument"
                }
            )
            self.publish_topic(custom_control_topic, res)
            return
        status = int(status_str)
        if status == 1:
            res = json.dumps(
                {
                    "status": 0,
                    "message": "receive 1"
                }
            )
            self.publish_topic(custom_control_topic, res)

        elif status == 2:
            res = json.dumps(
                {
                    "status": 0,
                    "message": "receive 2"
                }
            )
            self.publish_topic(custom_control_topic, res)
            self.obj.setLightColor({"R": 60, "G": 60, "B": 60})
        else:
            res = json.dumps(
                {
                    "status": 0,
                    "message": "unknow value"
                }
            )
            self.publish_topic(custom_control_topic, res)

    def run(self):
        self.client.loop_forever()

# def run():
#     broker = '192.168.211.165'
#     port = 1883
#     # generate client ID with pub prefix randomly
#     client_id = f'python-mqtt-{random.randint(0, 100)}'
#     mq = WuxiMqttClass(broker=broker, port=port, client_id=client_id)
#     # print(mq)
#     mq.subscribe_topic_received('wuxi/#')
#     mq.client.loop_forever()


if __name__ == '__main__':
    broker = '192.168.211.182'
    port = 1883
    # log = Logger('log_record.log', level='debug')
    mq = WuxiMqttClass(broker, port)
    mq.subscribe_topic_received("wuxi/#")
    mq.run()